import cloneDeep from 'lodash/cloneDeep';
import sum from 'lodash/sum';

/**
 * 数组转树
 * @param array
 * @param idKey
 * @param pIdKey
 * @returns {[]}
 */
export function array2Tree(array, idKey = 'id', pIdKey = 'pId') {
    const newArray = cloneDeep(array);
    const result = [];
    const map = {};
    newArray.forEach(item => {
        map[item[idKey]] = item;
    });
    newArray.forEach(item => {
        const parent = map[item[pIdKey]];
        if (parent) {
            (parent.children || (parent.children = [])).push(item);
        } else {
            result.push(item);
        }
    });
    return result;
}

/**
 * 树结构数据转换为数组格式
 * @param treeData
 * @param childrenKey
 * @returns {Array}
 */
export function tree2array(treeData, childrenKey = 'children') {
    const treeDataClone = cloneDeep(treeData);
    if (!treeDataClone || treeDataClone.length === 0) {
        return [];
    }
    let result = [];
    // eslint-disable-next-line no-plusplus
    for (let i = 0; i < treeDataClone.length; i += 1) {
        if (treeDataClone[i][childrenKey] && treeDataClone[i][childrenKey].length) {
            result = result.concat(tree2array(treeDataClone[i][childrenKey], childrenKey));
        }
        delete treeDataClone[i][childrenKey];
        result.push(treeDataClone[i]);
    }
    return result;
}

/**
 * 为没有父节点的树数据添加父节点
 * @param treeData
 * @param idKey
 * @param pidKey
 * @param childrenKey
 * @returns {Array}
 */
export function putTreeDataPid(treeData, idKey = 'id', pidKey = 'pId', childrenKey = 'children') {
    const treeDataClone = cloneDeep(treeData);
    if (!treeDataClone || treeDataClone.length === 0) {
        return [];
    }
    for (let i = 0; i < treeDataClone.length; i += 1) {
        treeDataClone[i][childrenKey] = putTreeDataPid(
            treeDataClone[i][childrenKey] &&
                treeDataClone[i][childrenKey].map(item => {
                    const newItem = cloneDeep(item);
                    newItem[pidKey] = newItem[pidKey] || treeDataClone[i][idKey];
                    return newItem;
                })
        );
    }
    return treeDataClone;
}

/**
 * 寻找树节点
 * @param treeData
 * @param targetId
 * @param idKey
 * @param childrenKey
 * @returns {any}
 */
export function findTreeData(treeData, targetId, idKey = 'id', childrenKey = 'children') {
    let result = null;
    if (!treeData || treeData.length === 0) {
        return null;
    }
    // eslint-disable-next-line no-plusplus
    for (let i = 0; i < treeData.length; i++) {
        if (treeData[i][idKey] === targetId) {
            result = treeData[i];
        } else if (treeData[i][childrenKey] && treeData[i][childrenKey].length) {
            result = findTreeData(treeData[i]?.children, targetId, idKey, childrenKey);
        }
        if (result) {
            break;
        }
    }

    return result;
}

/**
 * 过滤树数据. 如果子节点有匹配数据, 会连带父节点一起返回
 * @param array 要过滤的数组数据
 * @param filterFn 过滤函数
 * @param idKey
 * @param pIdKey
 * @returns {*}
 */
export function filterTreeArrayData(array, filterFn, idKey = 'id', pIdKey = 'pId') {
    const result = array.filter(filterFn);
    const needCheekPidArr = [...result];
    // 查找父级
    while (needCheekPidArr.length) {
        const currentItemTemp = needCheekPidArr.splice(needCheekPidArr.length - 1, 1);
        const currentItem = currentItemTemp && currentItemTemp.length && currentItemTemp[0];
        if (currentItem[pIdKey]) {
            const parentItem = array.find(item => item[idKey] === currentItem[pIdKey]);
            if (parentItem && !result.some(item => item[idKey] === parentItem[idKey])) {
                result.unshift(parentItem);
                needCheekPidArr.push(parentItem);
            }
        }
    }
    return result;
}

/**
 * 过滤树类型数据
 * @param tree
 * @param compareFn
 * @returns {*}
 */
export function filterTreeData(tree, compareFn) {
    return cloneDeep(tree)
        .map(arrayItem => {
            if (arrayItem.children) {
                // eslint-disable-next-line no-param-reassign
                arrayItem.children = filterTreeData(arrayItem.children, compareFn).filter(item => !!item);
                // 如果子节点有匹配的结果, 就直接返回父节点
                if (arrayItem.children.length) {
                    return arrayItem;
                }
            }
            if (compareFn && compareFn(arrayItem)) {
                return arrayItem;
            }
            // 返回空值, 用来给父级做过滤
            return null;
        })
        .filter(item => !!item); // 过滤掉空值
}

/**
 * 遍历树类型数据
 * @param tree
 * @param fn
 * @returns {*}
 */
export function mapTreeData(tree, fn) {
    return cloneDeep(tree).map(item => {
        if (item.children) {
            // eslint-disable-next-line no-param-reassign
            item.children = mapTreeData(item.children, fn);
        }
        if (fn) {
            return fn(item);
        }
        return item;
    });
}

/**
 * 向上查找所有父节点
 * @param array 数组类型数据
 * @param targetItem 要查找的节点
 * @param idKey
 * @param pidKey
 * @returns {[]} 所有父节点数据
 */
export function findParentItemInTreeArray(array, targetItem, idKey = 'id', pidKey = 'pId') {
    const result = [];
    let currentItem = targetItem;
    const findItem = () => array.find(item => item[idKey] === currentItem[pidKey]);
    do {
        currentItem = findItem();
        if (currentItem) {
            result.unshift(currentItem);
        }
    } while (currentItem && currentItem[pidKey]);
    return result;
}

/**
 * 向上查找所有父节点
 * @param array 数组类型数据
 * @param currentKey 要查找的节点key
 * @param idKey
 * @param pidKey
 * @returns {[]} 所有父节点数据
 */
export function closestParentKeysInTreeArray(array, currentKey, idKey = 'id', pidKey = 'pId') {
    const result = [];
    let currentItem = array.find(item => item[idKey] === currentKey);
    if (!currentItem) {
        return result;
    }
    const findItem = () => array.find(item => item[idKey] === currentItem[pidKey]);
    do {
        currentItem = findItem();
        if (currentItem) {
            result.unshift(currentItem[idKey]);
        }
    } while (currentItem && currentItem[pidKey]);
    return result;
}

/**
 * 向下查找所有子节点
 * @param array 数组类型数据
 * @param targetItem 要查找的节点
 * @param idKey
 * @param pidKey
 * @returns {[]} 所有父节点数据
 */
export function findChildrenItemInTreeArray(array, targetItem, idKey = 'id', pidKey = 'pId') {
    const result = [];
    const findChildren = pId => array.filter(item => item[pidKey] === pId);
    let queue = findChildren(targetItem[idKey]);
    while (queue.length) {
        const currentItem = queue.shift();
        const children = findChildren(currentItem[idKey]);
        result.push(currentItem);
        queue = queue.concat(children);
    }
    return result;
}

/**
 * 替换树节点数据
 * @param treeData 树类型数据
 * @param replaceFieldName 需要替换的目标字段名
 * @param fieldValue 需要替换的目标字段值
 * @param replaceNode 要替换的值
 * @returns {[]}
 */
export function replaceTreeNode(treeData = [], replaceFieldName, fieldValue, replaceNode) {
    return treeData.map(item => {
        const { children } = item;
        let result = { ...item };
        if (item[replaceFieldName] === fieldValue) {
            result = { ...result, ...replaceNode };
        } else if (children && Array.isArray(children) && children.length) {
            result.children = replaceTreeNode(children, replaceFieldName, fieldValue, replaceNode);
        }
        return result;
    });
}

/**
 * 删除空的 children 节点
 *
 * @export
 * @param treeData 树类型数据
 * @returns {[]}
 */
export function removeEmptyChildren(treeData = []) {
    return (
        Array.isArray(treeData) &&
        treeData.map(item => {
            const result = { ...item };
            const { children } = result;
            if (Array.isArray(children) && children.length) {
                result.children = removeEmptyChildren(children);
            } else {
                delete result.children;
            }
            return result;
        })
    );
}

/*
 * 统计所有节点的所有子节点的数量
 * @param treeData 树类型数据
 * @param statisticsKey 统计好的数字保存在哪个字段
 * @returns {*}
 */
export function statisticsChildrenInTree(treeData, statisticsKey = 'statistics') {
    if (!treeData) {
        return [];
    }
    return treeData.map(item => {
        const newItem = { ...item };
        if (newItem.children && newItem.children.length) {
            newItem.children = statisticsChildrenInTree(newItem.children, statisticsKey);
            newItem[statisticsKey] = sum(newItem.children.map(childItem => childItem[statisticsKey] || 1));
        }
        return newItem;
    });
}

/**
 * 从一颗树种查找对应的值
 */
export function findValueInTree(treeData = [], fieldName, fieldValue, childrenName = 'children') {
    let result;

    function findNode(tree) {
        // eslint-disable-next-line no-plusplus
        for (let i = 0; i < tree.length; i++) {
            if (tree[i][fieldName] === fieldValue) {
                result = tree[i];
                break;
            } else if (tree[i][childrenName] && tree[i][childrenName].length) {
                findNode(tree[i][childrenName]);
            }
        }
    }
    findNode(treeData);

    return result;
}

/**
 * 替换所有子节点的目标值
 */
function replaceSubNode(subTreeData = [], effectSubObj) {
    return subTreeData.map(subItem => {
        let subResult = { ...subItem };
        const { children } = subResult;
        subResult = { ...subResult, ...effectSubObj };
        if (Array.isArray(children) && children.length) {
            subResult.children = replaceSubNode(children, effectSubObj);
        }
        return subResult;
    });
}

/**
 * 父节点影响子节点
 *
 */
export function effectSubNode(treeData = [], fieldName, fieldValue, effectObj = {}) {
    return treeData.map(item => {
        let result = { ...item };
        const { children } = result;
        if (item[fieldName] === fieldValue) {
            result = { ...result, ...effectObj };
            if (Array.isArray(children) && children.length) {
                result.children = replaceSubNode(children, effectObj);
            }
        } else if (Array.isArray(children) && children.length) {
            result.children = effectSubNode(children, fieldName, fieldValue, effectObj);
        }
        return result;
    });
}

export const getTreeNodePath = (tree = [], fieldName, fieldValue, childrenName = 'children') => {
    let treeData = tree;
    let result = [];

    if (!Array.isArray(tree)) {
        treeData = [tree];
    }

    for (let i = 0; i < treeData.length; i += 1) {
        if (treeData[i][fieldName] === fieldValue) {
            result.push(treeData[i]);
            break;
        }
        if (treeData[i][childrenName] && treeData[i][childrenName].length) {
            result = result.concat(getTreeNodePath(treeData[i][childrenName], fieldName, fieldValue, childrenName));
            if (result.length) {
                result.unshift(treeData[i]);
                break;
            }
        }
    }
    return result;
};

/**
 * 子节点影响父节点
 */
export function effectParentNode(treeData = [], fieldName, fieldValue, effectObj) {
    const parentPathArray = getTreeNodePath(treeData, fieldName, fieldValue);
    let result = treeData;
    parentPathArray.forEach(item => {
        const { code } = item;
        result = replaceTreeNode(result, fieldName, code, effectObj);
    });
    return result;
}

/**
 * 判断在数组中是否有子节点
 * @param array
 * @param targetNode
 * @param idKey
 * @param pidKey
 * @returns {*}
 */
export function hasChildrenNode(array, targetNode, idKey = 'id', pidKey = 'pId') {
    return array.some(item => item[pidKey] === targetNode[idKey]);
}

/**
 * 扁平化树结构
 * @param data
 * @returns {[]}
 */
export function flattenTree(data) {
    const result = [];
    const deep = tree => {
        for (let i = 0; i < tree.length; i += 1) {
            const node = tree[i];
            result.push(node);
            if (node.children) {
                deep(node.children);
            }
        }
    };
    if (data instanceof Array) {
        deep(cloneDeep(data));
    } else {
        deep([cloneDeep(data)]);
    }
    return result;
}
